package com.yanqu.road.server.manger.config;

import com.yanqu.road.entity.clinic.DepartmentData;
import com.yanqu.road.entity.clinic.DiseaseData;
import com.yanqu.road.entity.clinic.UserClinicData;
import com.yanqu.road.entity.config.clinic.*;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.logic.bussiness.config.ClinicConfigBusiness;
import com.yanqu.road.logic.bussiness.config.NpcConfigBussiness;
import com.yanqu.road.logic.bussiness.player.UserClinicBusiness;
import com.yanqu.road.pb.clinic.ClinicProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.clinic.ClinicModule;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.pb.ClinicPb;

import java.util.*;

/**
 * @author ：zfr
 * @date ：2021/2/25 14:39
 * 医馆配置
 */
public class ClinicMgr extends TempMgr {
    /**
     * 科室等级配置map
     * departmentId - level - departmentLv
     */
    private static Map<Integer, Map<Integer, DepartmentLv>> departmentLvMap;
    /**
     * 病症配置map
     * diseaseId - diseaseInfo
     */
    private static Map<Integer, DiseaseInfo> diseaseInfoMap;
    /**
     * 病人配置
     * patientId - patientInfo
     */
    private static Map<Integer, PatientInfo> patientInfoMap;
    /**
     * 事件配置
     * eventId - eventInfo
     */
    private static Map<Integer, ClinicEventInfo> eventInfoMap;

    public static DepartmentLv getDepartmentLv(int type, int level) {
        if (!departmentLvMap.containsKey(type)) {
            return null;
        }
        return departmentLvMap.get(type).get(level);
    }

    public static Map<Integer, Map<Integer, DepartmentLv>> getDepartmentLvMap() {
        return departmentLvMap;
    }

    public static DiseaseInfo getDiseaseInfo(int diseaseId) {
        return diseaseInfoMap.get(diseaseId);
    }

    public static ClinicEventInfo getEventInfo(int eventId) {
        return eventInfoMap.get(eventId);
    }

    public static PatientInfo getPatientInfo(int patientId) {
        return patientInfoMap.get(patientId);
    }

    /**
     * 获取科室当前第一个未解锁的病症
     * @param type  科室类型
     * @param level 等级
     * @return
     */
    public static int getFirstLockDisease(int type, int level) {
        DepartmentLv departmentLv = getDepartmentLv(type, level + 1);
        if (departmentLv != null) {
            if (departmentLv.getUnlockDiseaseId() == 0) {
                getFirstLockDisease(type, departmentLv.getLevel());
            } else {
                return departmentLv.getUnlockDiseaseId();
            }
        }
        return 0;
    }

    /**
     * 默认病人解锁
     * @return
     */
    public static List<Integer> unLockPatientDefault() {
        List<Integer> list = new ArrayList<>();
        for (PatientInfo patientInfo : patientInfoMap.values()) {
            if (patientInfo.getUnlockScore() <= 0) {
                list.add(patientInfo.getPatientId());
            }
        }
        return list;
    }

    /**
     * 拜访玩家医馆
     * @param otherPlayerId
     * @return
     */
    public static ClinicProto.VisitOtherClinicRespMsg.Builder visitClinic(long otherPlayerId) {
        GamePlayer onlinePlayer = GamePlayerMgr.getOnlinePlayer(otherPlayerId);
        UserClinicData userClinicData;
        UserInfo userInfo = UserMgr.getUserInfo(otherPlayerId);
        if (onlinePlayer != null) {
            userClinicData = onlinePlayer.getModule(ClinicModule.class).getUserClinicData();
        } else {
            //读库
            userClinicData = UserClinicBusiness.getUserClinicData(otherPlayerId);
            Map<Integer, DepartmentData> departmentDataMap = UserClinicBusiness.getDepartmentDataMap(otherPlayerId);
            Map<Integer, DiseaseData> diseaseDataMap = UserClinicBusiness.getDiseaseDataMap(otherPlayerId);
            userClinicData.setDepartmentMap(departmentDataMap);
            userClinicData.setDiseaseDataMap(diseaseDataMap);
        }
        return ClinicPb.parseVisitClinicMsg(userClinicData, userInfo);
    }

    /**
     * 获取上一个病人id
     * @param patientId
     * @return
     */
    public static int getLastPatientId(int patientId) {
        List<PatientInfo> patientInfos = new ArrayList<>(patientInfoMap.values());
        patientInfos.sort(Comparator.comparing(PatientInfo::getSort));
        for (int i = 0; i < patientInfos.size(); i++) {
            if (patientInfos.get(i).getPatientId() == patientId) {
                if (i == 0) {
                    return patientId;
                } else {
                    return patientInfos.get(i - 1).getPatientId();
                }
            }
        }
        return -1;
    }

    @Override
    public boolean reloadConfig() throws Exception {
        departmentLvMap = ClinicConfigBusiness.getDepartmentLvMap();
        diseaseInfoMap = ClinicConfigBusiness.getDiseaseInfoMap();
        patientInfoMap = ClinicConfigBusiness.getPatientInfoMap();
        eventInfoMap = NpcConfigBussiness.getClinicEventMap();
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean stop() {
        return false;
    }

    public static List<OffLineCureCostTime> parseOffLineCureCostTimeList(String config) {
        String[] split = config.split("\\|");
        List<OffLineCureCostTime> OffLineCureCostTimeList = new ArrayList<>();
        long lastEndPoint = 0;
        for (int i = 0; i < split.length; i++) {
            int endPoint = Integer.MAX_VALUE;
            String beginStr = split[i];
            if (i + 1 < split.length) {
                String endStr = split[i + 1];
                String[] split2 = endStr.split(";");
                endPoint = Integer.parseInt(split2[0]);
            }
            String[] split1 = beginStr.split(";");
            int beginPoint = Integer.parseInt(split1[0]);
            if (beginPoint != lastEndPoint || beginPoint > endPoint) {
                throw new RuntimeException("OFFLINE_COST_TIME config is error!");
            }
            lastEndPoint = endPoint;
            OffLineCureCostTime offLineCureCostTime = new OffLineCureCostTime();
            offLineCureCostTime.setBeginPoint(beginPoint);
            offLineCureCostTime.setEndPoint(endPoint);
            offLineCureCostTime.setCostTimeSecond(Integer.parseInt(split1[1]));
            OffLineCureCostTimeList.add(offLineCureCostTime);
        }
        OffLineCureCostTimeList.sort(Comparator.comparing(OffLineCureCostTime::getBeginPoint).reversed());
        return OffLineCureCostTimeList;
    }

    public static long calcOffLineCureCount(long curReceptionCount, long offLineDuringTime, String config) {
        long needCureCount = 0;
        //分段
        for (OffLineCureCostTime offLineCureCostTime : parseOffLineCureCostTimeList(config)) {
            if (curReceptionCount > offLineCureCostTime.getBeginPoint() && curReceptionCount <= offLineCureCostTime.getEndPoint()) {
                long thisRegionCureCount = Math.min(offLineDuringTime / offLineCureCostTime.getCostTimeSecond(), curReceptionCount - offLineCureCostTime.getBeginPoint());
                needCureCount += thisRegionCureCount;
                curReceptionCount -= thisRegionCureCount;
                offLineDuringTime -= thisRegionCureCount * offLineCureCostTime.getCostTimeSecond();

                if (curReceptionCount <= 0 || offLineDuringTime <= offLineCureCostTime.getCostTimeSecond()) {
                    break;
                }
            }
        }
        return needCureCount;
    }

    public static long calcOffLineCureCostTime(long curReceptPatientNum, long realCureNum, String config) {
        long offLineCureNeedTime = 0;
        for (OffLineCureCostTime offLineCureCostTime : parseOffLineCureCostTimeList(config)) {
            if (curReceptPatientNum > offLineCureCostTime.getBeginPoint() && curReceptPatientNum <= offLineCureCostTime.getEndPoint()) {
                long thisRegionCureCount = Math.min(curReceptPatientNum - offLineCureCostTime.getBeginPoint(), realCureNum);
                offLineCureNeedTime += thisRegionCureCount * offLineCureCostTime.getCostTimeSecond();
                realCureNum -= thisRegionCureCount;
                curReceptPatientNum -= thisRegionCureCount;
                if (realCureNum <= 0) {
                    break;
                }
            }
        }
        return offLineCureNeedTime;
    }
}
